package com.brainhealth.quartz.service.impl;

import com.brainhealth.common.constant.CacheConstants;
import com.brainhealth.common.constant.Constants;
import com.brainhealth.common.constant.PunctuationConstants;
import com.brainhealth.common.core.redis.RedisCache;
import com.brainhealth.common.enums.CustomerExerciseStatus;
import com.brainhealth.common.enums.PayStatus;
import com.brainhealth.common.enums.PushUserTypeEnum;
import com.brainhealth.common.enums.YNEnum;
import com.brainhealth.common.utils.DateUtils;
import com.brainhealth.common.utils.LongUtils;
import com.brainhealth.common.utils.StringUtils;
import com.brainhealth.customer.domain.*;
import com.brainhealth.customer.service.*;
import com.brainhealth.quartz.service.IChatJobService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wll
 * 聊天定时任务
 */
@Service
public class IChatJobServiceImpl implements IChatJobService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    IChatRecordService chatRecordService;
    @Autowired
    IWebsocketService websocketService;
    @Autowired
    ICustomerService customerService;
    @Autowired
    ISysLoginPushService sysLoginPushService;
    @Autowired
    IChatMainService chatMainService;
    @Autowired
    ICustomerExerciseService customerExerciseService;
    @Autowired
    IExerciseOrderService exerciseOrderService;
    @Autowired
    private IExerciseService exerciseService;
    @Autowired
    RedisCache redisCache;

    /**
     * 清理聊天记录
     */
    @Override
    public void clearChatRecord() {
        try {
            long tid = DateUtils.getTimeMillis();
            Date beginDate = new Date();
            logger.info("tid：{},【清理聊天记录】,开始时间：{}", tid, DateUtils.getTime());
            //1、查询用户
            List<String> customerIdList = chatRecordService.selectCustomerIdList();
            if (CollectionUtils.isEmpty(customerIdList)) {
                return;
            }
            logger.info("tid：{},【清理聊天记录】,用户数：{}", tid, customerIdList.size());
            //2、遍历用户
            for (String customerId : customerIdList) {
                //3、需要删除的会员聊天主键集合
                List<String> recordIdList = chatRecordService.selectRecordIdList(Long.valueOf(customerId));
                Long[] longRecordIdArr = LongUtils.string2LongArr(recordIdList);
                if (null != longRecordIdArr && longRecordIdArr.length > 0) {
                    //4、清除(聊天记录)数据
                    int count = chatRecordService.deleteChatRecordByIds(longRecordIdArr);
                    logger.info("tid：{},【清理聊天记录】,用户：{}, 清理聊天记录条数：{}", tid, customerId, count);
                }
            }
            logger.info("tid：{},【清理聊天记录】,结束时间：{}", tid, DateUtils.getTime());
            Date endDate = new Date();
            logger.info("tid：{},【清理聊天记录】,耗时：{}", tid, DateUtils.differentMinuteByMillisecond(beginDate, endDate));
        } catch (Exception e) {
            logger.error("清理聊天记录异常：", e);
        }
    }

    /**
     * 1.查询全部用户
     * 2.查看用户是否满足推送条件
     * 3.如果满足推送条件，推送消息
     */
    @Override
    public void pushLogin() {
        long ts = DateUtils.getTimeMillis();
        try {
            logger.info("ts:{}，登录消息推送开始", ts);
            List<Customer> onlineCustomerList = websocketService.getOnlineCustomerList();
            List<SysLoginPush> sysLoginPushList = sysLoginPushService.selectSysLoginPushList(null);
            for (SysLoginPush loginPush : sysLoginPushList) {
                Integer pushSwitch = loginPush.getPushSwitch();
                if (pushSwitch.equals(YNEnum.NO.getCode())) {
                    continue;
                }
                Long taskId = loginPush.getTaskId();
                String pushContent = loginPush.getPushContent();
                Integer pushUserType = loginPush.getPushUserType();
                String pushUsers = loginPush.getPushUser();
                Integer pushCondition = loginPush.getPushCondition();
                List<Customer> customerList = getSettingPushUserList(pushUserType, pushUsers);
                List<Customer> pushUserList = getPushUserList(onlineCustomerList, customerList, pushCondition);
                for (Customer customer : pushUserList) {
                    String customerPhone = customer.getPhone();
                    String cacheKey = String.format("%s:%s:%s", CacheConstants.PUSH_LOGIN_KEY, taskId, customerPhone);
                    Object cacheObject = redisCache.getCacheObject(cacheKey);
                    if (null == cacheObject) {
                        if (StringUtils.isNotBlank(pushContent)) {
                            pushContent = pushContent.replace(Constants.MARK_NAME, customer.getNickName());
                        }
                        websocketService.pushMsgToOne(customerPhone, pushContent);
                        logger.info("ts:{}用户ID：{}登录消息推送完成", ts, customer.getPhone());
                        redisCache.setCacheObject(cacheKey, Constants.PUSH_LOGIN_FLAG);
                        logger.info("ts:{}用户ID：{}登录消息推送，写入缓存成功，缓存KEY：{}", ts, customerPhone, cacheKey);
                    }
                }
            }
            logger.info("ts:{}，登录消息推送结束", ts);
        } catch (Exception e) {
            logger.error("ts:{},登录推送异常，", ts, e);
        }
    }

    /**
     *  1.遍历chat_main ，筛选当前时间>next_open_time数据
     *  2.去exercise_order表，将当前订单状态置为完成，将next_order_no订单状态置为训练中
     */
    @Override
    public void openNextTask() {
        long ts = DateUtils.getTimeMillis();
        try {
            logger.info("ts:{} 开启下一订单任务开始=====================================",ts);
            List<ChatMain> chatMainList = chatMainService.selectChatMainList(null);
            if (io.jsonwebtoken.lang.Collections.isEmpty(chatMainList)) {
                logger.info("{} 未查询到聊天主表数据", ts);
                return;
            }

            for (ChatMain chatMain : chatMainList) {
                if (null == chatMain || null == chatMain.getCustomerId()) {
                    logger.warn("ts:{}id为{}的聊天主表为空或用户ID为空,", ts, chatMain.getId());
                    continue;
                }
                Customer customer=new Customer();
                customer.setCustomerId(chatMain.getCustomerId());
                CustomerExercise customerExercise = new CustomerExercise();
                customerExercise.setCustomerId(customer.getCustomerId());
                customerExercise.setOrderId(chatMain.getOrderNo());
                customerExercise.setStatus(CustomerExerciseStatus.Finished);
                List<CustomerExercise> finishedCustomerExerciseList = customerExerciseService.selectCustomerExerciseList(customerExercise);
                customerExercise.setStatus(CustomerExerciseStatus.expired);
                List<CustomerExercise> expiredCustomerExerciseList = customerExerciseService.selectCustomerExerciseList(customerExercise);

                if (StringUtils.isNotBlank(chatMain.getOrderNo())
                        && StringUtils.isNotBlank(chatMain.getNextOrderNo())
                        &&  exerciseService.getCompletedState(finishedCustomerExerciseList,expiredCustomerExerciseList)
                        && null != chatMain.getNextOpenTime()
                        && DateUtils.compare(new Date(), chatMain.getNextOpenTime())) {
                    openNextOrderTask(chatMain,ts);
                }
            }

            logger.info("ts:{} 开启下一订单任务结束=====================================",ts);
        } catch (Exception e) {
            logger.error("ts{}，开启下一订单任务异常",ts, e);
        }
    }

    @Transactional
    void openNextOrderTask(ChatMain chatMain,Long ts)
    {
        logger.info("ts:{}，用户{}开启下一个订单任务**********************", ts, chatMain.getCustomerId());
        //1.更新训练中的订单为已完成状态
        ExerciseOrder exerciseOrder = new ExerciseOrder();
        exerciseOrder.setCustomerId(chatMain.getCustomerId());
        exerciseOrder.setOrderId(chatMain.getOrderNo());
        exerciseOrder.setStatus(PayStatus.Exercise);
        List<ExerciseOrder> exerciseOrderList = exerciseOrderService.selectExerciseOrderList(exerciseOrder);
        if (org.springframework.util.CollectionUtils.isEmpty(exerciseOrderList)) {
            logger.info("ts:{} 用户{}无训练中的订单", ts, chatMain.getCustomerId());
        }
        exerciseOrder.setStatus(PayStatus.Finish);
        exerciseOrder.setExerciseOrderId(exerciseOrderList.get(0).getExerciseOrderId());
        int updateExerciseResult = exerciseOrderService.updateExerciseOrder(exerciseOrder);
        logger.info("ts:{}，【1】更新订单为完成状态，结果：{}", ts, updateExerciseResult);

        //2.更新已支付订单状态为训练中状态
        exerciseOrder.setOrderId(chatMain.getNextOrderNo());
        exerciseOrder.setStatus(PayStatus.Paid);
        exerciseOrderList = exerciseOrderService.selectExerciseOrderList(exerciseOrder);
        if (org.springframework.util.CollectionUtils.isEmpty(exerciseOrderList)) {
            logger.info("ts:{} 用户{}无已支付的订单", ts, chatMain.getCustomerId());
        }
        exerciseOrder.setStatus(PayStatus.Exercise);
        exerciseOrder.setExerciseOrderId(exerciseOrderList.get(0).getExerciseOrderId());
        int updatePaidResult = exerciseOrderService.updateExerciseOrder(exerciseOrder);
        logger.info("ts:{}，【2】更新订单为训练中状态，结果：{}", ts, updatePaidResult);

        //3.更新聊天主表
        ChatMain updateChatMain=new ChatMain();
        updateChatMain.setId(chatMain.getId());
        updateChatMain.setNextOpenTime(null);
        updateChatMain.setNextOrderNo("");
        int updateResult = chatMainService.updateChatMain(updateChatMain);
        logger.info("ts:{}，【3】更新下一订单及开启状态，结果：{}", ts, updateResult);

        logger.info("ts:{}，用户{}开启下一个订单任务结束**********************", ts, chatMain.getCustomerId());
    }

    private List<Customer> getSettingPushUserList(Integer pushUserType, String userIds) {
        if (pushUserType.equals(PushUserTypeEnum.ALL.getCode())) {
            return customerService.selectCustomerList(null);
        }
        String[] ids = userIds.split(PunctuationConstants.COMMA);
        List<String> idArr = Arrays.asList(ids);
        List<Long> longIdList = LongUtils.string2LongList(idArr);
        return customerService.selectCustomerByCustomerIds(longIdList);
    }

    private List<Customer> getPushUserList(List<Customer> onlineCustomerList, List<Customer> customerList, Integer logoutDays) {
        List<Customer> customerIdList = new ArrayList<>();
        List<Customer> intersection = onlineCustomerList.stream().filter(item -> customerList.contains(item)).collect(Collectors.toList());
        for (Customer customer : intersection) {
            Date date = new Date();
            Date loginTime = customer.getLoginTime();
            int days = DateUtils.differentDaysByMillisecond(loginTime, date);
            if (logoutDays == days) {
                customerIdList.add(customer);
            }
        }
        return customerIdList;
    }

}
